package com.example.inventoryservice.actor;

import akka.actor.AbstractActor;
import akka.actor.Props;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import com.example.inventoryservice.event.*;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 库存Actor
 * 处理库存相关的业务逻辑，响应订单事件
 */
@Component("inventoryActor")
public class InventoryActor extends AbstractActor {

    private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);
    
    // 模拟库存数据存储
    private final Map<String, Integer> inventory = new ConcurrentHashMap<>();
    
    // 模拟订单预留库存
    private final Map<String, Map<String, Integer>> reservedInventory = new ConcurrentHashMap<>();

    public static Props props() {
        return Props.create(InventoryActor.class);
    }

    @Override
    public void preStart() {
        // 初始化一些测试库存数据
        inventory.put("PRODUCT_001", 100);
        inventory.put("PRODUCT_002", 50);
        inventory.put("PRODUCT_003", 200);
        log.info("库存Actor启动，初始库存: {}", inventory);
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .match(ReserveInventory.class, this::handleReserveInventory)
                .match(ConfirmInventory.class, this::handleConfirmInventory)
                .match(ReleaseInventory.class, this::handleReleaseInventory)
                .match(GetInventoryStatus.class, this::handleGetInventoryStatus)
                .matchAny(o -> log.warning("收到未知消息: {}", o))
                .build();
    }

    /**
     * 处理预留库存命令
     */
    private void handleReserveInventory(ReserveInventory reserveInventory) {
        log.info("处理预留库存请求: 订单ID={}, 商品列表={}", 
            reserveInventory.getOrderId(), reserveInventory.getItems());
        
        try {
            Map<String, Integer> orderReservation = new HashMap<>();
            boolean canReserve = true;
            
            // 检查库存是否足够
            for (OrderItem item : reserveInventory.getItems()) {
                String productId = item.getProductId();
                Integer requestedQty = item.getQuantity();
                Integer availableQty = inventory.getOrDefault(productId, 0);
                
                if (availableQty < requestedQty) {
                    canReserve = false;
                    log.warning("库存不足: 商品ID={}, 请求数量={}, 可用数量={}", 
                        productId, requestedQty, availableQty);
                    break;
                }
                
                orderReservation.put(productId, requestedQty);
            }
            
            if (canReserve) {
                // 预留库存
                reservedInventory.put(reserveInventory.getOrderId(), orderReservation);
                
                // 减少可用库存
                for (Map.Entry<String, Integer> entry : orderReservation.entrySet()) {
                    String productId = entry.getKey();
                    Integer reservedQty = entry.getValue();
                    inventory.put(productId, inventory.get(productId) - reservedQty);
                }
                
                log.info("库存预留成功: 订单ID={}, 预留详情={}", 
                    reserveInventory.getOrderId(), orderReservation);
                
                getSender().tell(new InventoryReserved(reserveInventory.getOrderId(), "SUCCESS", orderReservation), getSelf());
            } else {
                log.warning("库存预留失败: 订单ID={}, 库存不足", reserveInventory.getOrderId());
                getSender().tell(new InventoryReserved(reserveInventory.getOrderId(), "INSUFFICIENT_INVENTORY", null), getSelf());
            }
            
        } catch (Exception e) {
            log.error("预留库存异常: {}", e.getMessage(), e);
            getSender().tell(new InventoryReserved(reserveInventory.getOrderId(), "ERROR", null), getSelf());
        }
    }

    /**
     * 处理确认库存命令（订单支付后）
     */
    private void handleConfirmInventory(ConfirmInventory confirmInventory) {
        log.info("处理确认库存请求: 订单ID={}", confirmInventory.getOrderId());
        
        try {
            Map<String, Integer> reservation = reservedInventory.get(confirmInventory.getOrderId());
            if (reservation != null) {
                // 确认预留的库存，不需要额外操作
                log.info("库存确认成功: 订单ID={}, 确认详情={}", 
                    confirmInventory.getOrderId(), reservation);
                getSender().tell(new InventoryConfirmed(confirmInventory.getOrderId(), "SUCCESS"), getSelf());
            } else {
                log.warning("未找到预留库存: 订单ID={}", confirmInventory.getOrderId());
                getSender().tell(new InventoryConfirmed(confirmInventory.getOrderId(), "NOT_FOUND"), getSelf());
            }
            
        } catch (Exception e) {
            log.error("确认库存异常: {}", e.getMessage(), e);
            getSender().tell(new InventoryConfirmed(confirmInventory.getOrderId(), "ERROR"), getSelf());
        }
    }

    /**
     * 处理释放库存命令（订单取消后）
     */
    private void handleReleaseInventory(ReleaseInventory releaseInventory) {
        log.info("处理释放库存请求: 订单ID={}", releaseInventory.getOrderId());
        
        try {
            Map<String, Integer> reservation = reservedInventory.remove(releaseInventory.getOrderId());
            if (reservation != null) {
                // 释放预留的库存
                for (Map.Entry<String, Integer> entry : reservation.entrySet()) {
                    String productId = entry.getKey();
                    Integer releasedQty = entry.getValue();
                    inventory.put(productId, inventory.get(productId) + releasedQty);
                }
                
                log.info("库存释放成功: 订单ID={}, 释放详情={}", 
                    releaseInventory.getOrderId(), reservation);
                getSender().tell(new InventoryReleased(releaseInventory.getOrderId(), "SUCCESS"), getSelf());
            } else {
                log.warning("未找到预留库存: 订单ID={}", releaseInventory.getOrderId());
                getSender().tell(new InventoryReleased(releaseInventory.getOrderId(), "NOT_FOUND"), getSelf());
            }
            
        } catch (Exception e) {
            log.error("释放库存异常: {}", e.getMessage(), e);
            getSender().tell(new InventoryReleased(releaseInventory.getOrderId(), "ERROR"), getSelf());
        }
    }

    /**
     * 处理获取库存状态命令
     */
    private void handleGetInventoryStatus(GetInventoryStatus getStatus) {
        log.info("处理获取库存状态请求");
        
        try {
            Map<String, Object> status = new HashMap<>();
            status.put("availableInventory", new HashMap<>(inventory));
            status.put("reservedInventory", new HashMap<>(reservedInventory));
            
            getSender().tell(new InventoryStatus(status), getSelf());
            
        } catch (Exception e) {
            log.error("获取库存状态异常: {}", e.getMessage(), e);
            getSender().tell(new InventoryStatus(null), getSelf());
        }
    }

    // 命令消息类
    public static class ReserveInventory {
        private String orderId;
        private List<OrderItem> items;

        public ReserveInventory(String orderId, List<OrderItem> items) {
            this.orderId = orderId;
            this.items = items;
        }

        public String getOrderId() { return orderId; }
        public List<OrderItem> getItems() { return items; }
    }

    public static class ConfirmInventory {
        private String orderId;

        public ConfirmInventory(String orderId) {
            this.orderId = orderId;
        }

        public String getOrderId() { return orderId; }
    }

    public static class ReleaseInventory {
        private String orderId;

        public ReleaseInventory(String orderId) {
            this.orderId = orderId;
        }

        public String getOrderId() { return orderId; }
    }

    public static class GetInventoryStatus {
        public GetInventoryStatus() {}
    }

    // 响应消息类
    public static class InventoryReserved {
        private String orderId;
        private String status;
        private Map<String, Integer> reservedItems;

        public InventoryReserved(String orderId, String status, Map<String, Integer> reservedItems) {
            this.orderId = orderId;
            this.status = status;
            this.reservedItems = reservedItems;
        }

        public String getOrderId() { return orderId; }
        public String getStatus() { return status; }
        public Map<String, Integer> getReservedItems() { return reservedItems; }
    }

    public static class InventoryConfirmed {
        private String orderId;
        private String status;

        public InventoryConfirmed(String orderId, String status) {
            this.orderId = orderId;
            this.status = status;
        }

        public String getOrderId() { return orderId; }
        public String getStatus() { return status; }
    }

    public static class InventoryReleased {
        private String orderId;
        private String status;

        public InventoryReleased(String orderId, String status) {
            this.orderId = orderId;
            this.status = status;
        }

        public String getOrderId() { return orderId; }
        public String getStatus() { return status; }
    }

    public static class InventoryStatus {
        private Map<String, Object> status;

        public InventoryStatus(Map<String, Object> status) {
            this.status = status;
        }

        public Map<String, Object> getStatus() { return status; }
    }
}
